package com.gongyinlian.personalprofilewebsiteserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gongyinlian.personalprofilewebsiteserver.common.enums.ResultCode;
import com.gongyinlian.personalprofilewebsiteserver.common.exception.BusinessException;
import com.gongyinlian.personalprofilewebsiteserver.dto.LoginRequest;
import com.gongyinlian.personalprofilewebsiteserver.dto.RefreshTokenRequest;
import com.gongyinlian.personalprofilewebsiteserver.entity.SysUser;
import com.gongyinlian.personalprofilewebsiteserver.mapper.SysUserMapper;
import com.gongyinlian.personalprofilewebsiteserver.service.AuthService;
import com.gongyinlian.personalprofilewebsiteserver.utils.JwtUtil;
import com.gongyinlian.personalprofilewebsiteserver.utils.PasswordUtil;
import com.gongyinlian.personalprofilewebsiteserver.vo.LoginResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 认证服务实现类
 * 
 * @author personal-profile-website
 * @date 2024-10-27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
    
    private final SysUserMapper sysUserMapper;
    private final JwtUtil jwtUtil;
    
    @Override
    public LoginResponse login(LoginRequest request) {
        // 1. 查询用户
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, request.getUsername());
        SysUser user = sysUserMapper.selectOne(queryWrapper);
        
        // 2. 验证用户是否存在
        if (user == null) {
            log.warn("登录失败：用户不存在 - {}", request.getUsername());
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 3. 验证用户状态
        if (user.getStatus() == 0) {
            log.warn("登录失败：用户已被禁用 - {}", request.getUsername());
            throw new BusinessException(ResultCode.USER_DISABLED);
        }
        
        // 4. 验证密码
        if (!PasswordUtil.matches(request.getPassword(), user.getPassword())) {
            log.warn("登录失败：密码错误 - {}", request.getUsername());
            throw new BusinessException(ResultCode.PASSWORD_ERROR);
        }
        
        // 5. 生成Token
        String accessToken = jwtUtil.generateToken(user.getId(), user.getUsername());
        String refreshToken = jwtUtil.generateRefreshToken(user.getId());
        Long expiresIn = jwtUtil.getTokenRemainingTime(accessToken);
        
        // 6. 更新最后登录时间
        user.setLastLoginTime(java.time.LocalDateTime.now());
        user.setLastLoginIp(getClientIp());
        sysUserMapper.updateById(user);
        
        // 7. 构建响应
        LoginResponse response = LoginResponse.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .tokenType("Bearer")
                .expiresIn(expiresIn)
                .userId(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .role(user.getRole())
                .build();
        
        log.info("用户登录成功 - 用户名: {}, ID: {}", user.getUsername(), user.getId());
        return response;
    }
    
    @Override
    public LoginResponse refreshToken(RefreshTokenRequest request) {
        String refreshToken = request.getRefreshToken();
        
        // 1. 验证刷新Token
        if (!jwtUtil.validateToken(refreshToken)) {
            log.warn("刷新Token失败：Token无效");
            throw new BusinessException(ResultCode.TOKEN_INVALID);
        }
        
        // 2. 检查Token是否过期
        if (jwtUtil.isTokenExpired(refreshToken)) {
            log.warn("刷新Token失败：Token已过期");
            throw new BusinessException(ResultCode.TOKEN_EXPIRED);
        }
        
        // 3. 从Token中获取用户ID
        Long userId = jwtUtil.getUserIdFromToken(refreshToken);
        if (userId == null) {
            log.warn("刷新Token失败：无法获取用户ID");
            throw new BusinessException(ResultCode.TOKEN_INVALID);
        }
        
        // 4. 查询用户信息
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null) {
            log.warn("刷新Token失败：用户不存在 - ID: {}", userId);
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 5. 验证用户状态
        if (user.getStatus() == 0) {
            log.warn("刷新Token失败：用户已被禁用 - {}", user.getUsername());
            throw new BusinessException(ResultCode.USER_DISABLED);
        }
        
        // 6. 生成新的Token
        String newAccessToken = jwtUtil.generateToken(user.getId(), user.getUsername());
        String newRefreshToken = jwtUtil.generateRefreshToken(user.getId());
        Long expiresIn = jwtUtil.getTokenRemainingTime(newAccessToken);
        
        // 7. 构建响应
        LoginResponse response = LoginResponse.builder()
                .accessToken(newAccessToken)
                .refreshToken(newRefreshToken)
                .tokenType("Bearer")
                .expiresIn(expiresIn)
                .userId(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .role(user.getRole())
                .build();
        
        log.info("Token刷新成功 - 用户名: {}, ID: {}", user.getUsername(), user.getId());
        return response;
    }
    
    @Override
    public void logout(Long userId) {
        // 这里可以实现登出逻辑，比如：
        // 1. 将Token加入黑名单（如果使用Redis）
        // 2. 清除用户的在线状态
        // 3. 记录登出日志
        
        log.info("用户登出 - ID: {}", userId);
        
        // 当前简单实现：仅记录日志
        // Token的失效由客户端删除Token来实现
    }
    
    /**
     * 获取客户端IP地址
     * TODO: 在Controller中通过HttpServletRequest获取真实IP
     * 
     * @return IP地址
     */
    private String getClientIp() {
        // 这里返回默认值，实际应该从Request中获取
        return "127.0.0.1";
    }
}

